package com.yanfan.usersmart.user;



import cn.hutool.json.JSONObject;
import com.yanfan.usersmart.user.userInformation.UserInformationHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;


/**
 *
 * 用户传输装置-处理器
 *
 * @author youngki
 * @date 2022/10/20
 */

@Component
@ChannelHandler.Sharable
@Slf4j
public class UserSmartIotByKeAnHandler extends SimpleChannelInboundHandler<String> implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        applicationContext = context;
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception{
        log.info("客户端断开连接：");
        //执行客户端断开连接后的业务操作
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String data) throws Exception {
        //先确认校验值是否相等，再来确认要发送的数据是确定包，或者否定包    确定命令符:3  否定包：6

        //头
        String header = data.substring(0,4);
        //流水号
        String flow = data.substring(4,8);
        //版本号
        String version = data.substring(8,12);
        //时间
        String time = data.substring(12,24);
        //源地址  将源地址当作用传的编号
        String src = data.substring(24,36);
        String id=src.substring(10)+src.substring(8,10)+src.substring(6,8)+src.substring(4,6)+src.substring(2,4)
                +src.substring(0,2);
        //给用传设置一个设备编号
        String deviceCode = ByteUtil.buqi12(String.valueOf(new BigInteger(id,16))) ;
        //目的地址
        String mudi = data.substring(36,48);
        //有效数据长度
        String length = data.substring(48,52);
        String cmd = data.substring(52,54);
        //应用数据单元
        String raw = data.substring(54,data.length()-6);
        //crc 验证
        String crc = data.substring(data.length()-6,data.length()-4);
        //尾
        String end = data.substring(data.length()-4);
        //回复用传通用包
        byte [] me = checksumUser(header,flow,version,src,mudi,end);
        //回复用传包
        ctx.writeAndFlush(me);


        JSONObject jsonObject= new JSONObject();

        jsonObject.put("deviceCode", deviceCode);
        jsonObject.put("data",raw);
        jsonObject.put("hex",data);


        com.yanfan.usersmart.user.userInformation.DeviceSensorMessage deviceSensorMessage =
                new com.yanfan.usersmart.user.userInformation.DeviceSensorMessage();
        deviceSensorMessage.setId(deviceCode);
        deviceSensorMessage.setData(raw);
        //解析
        //UserInformationHandler userSmart = new UserInformationHandler();
        //userSmart.handle(deviceSensorMessage);
        UserInformationHandler userInformationHandler =
                applicationContext.getBean(UserInformationHandler.class);
        userInformationHandler.handle(deviceSensorMessage);
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = socket.getAddress().getHostAddress();
        log.info("收到客户端IP: " + ip);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();

        log.info(cause.getMessage());
//        ctx.close();
    }


    /**
     * 校验和用户
     *
     * @param headed  领导
     * @param flowId  流id
     * @param version 版本
     * @param src     src
     * @param mu
     * @param end     结束
     * @return {@link byte[]}
     */
    public byte [] checksumUser(String headed,String flowId,String version,String src,String mu,String end){

        Integer f1 = Integer.parseInt(flowId.substring(0,2),16);
        Integer f2 = Integer.parseInt(flowId.substring(2),16);
        Integer vma=Integer.parseInt(version.substring(0,2),16);
        Integer vmi=Integer.parseInt(version.substring(2),16);
        //同步心跳包时间
        Calendar now = Calendar.getInstance();
        Integer year=now.get(Calendar.YEAR)-2000;
        String hex_year = ByteUtil.buqi3(Integer.toHexString(year));
        Integer month=(now.get(Calendar.MONTH) + 1);
        String hex_month = ByteUtil.buqi3(Integer.toHexString(month));
        Integer day= now.get(Calendar.DAY_OF_MONTH);
        String hex_day= ByteUtil.buqi3(Integer.toHexString(day));
        Integer hour=now.get(Calendar.HOUR_OF_DAY);
        String hex_hour=ByteUtil. buqi3(Integer.toHexString(hour));
        Integer min=now.get(Calendar.MINUTE);
        String hex_min= ByteUtil.buqi3(Integer.toHexString(min));
        Integer sec=now.get(Calendar.SECOND);
        String hex_sec= ByteUtil.buqi3(Integer.toHexString(sec));



        Integer src0=Integer.parseInt(src.substring(0,2),16);
        Integer src1=Integer.parseInt(src.substring(2,4),16);
        Integer src2=Integer.parseInt(src.substring(4,6),16);
        Integer src3=Integer.parseInt(src.substring(6,8),16);
        Integer src4=Integer.parseInt(src.substring(8,10),16);
        Integer src5=Integer.parseInt(src.substring(10,12),16);

        Integer dest0=Integer.parseInt(mu.substring(0,2),16);
        Integer dest1=Integer.parseInt(mu.substring(2,4),16);
        Integer dest2=Integer.parseInt(mu.substring(4,6),16);
        Integer dest3=Integer.parseInt(mu.substring(6,8),16);
        Integer dest4=Integer.parseInt(mu.substring(8,10),16);
        Integer dest5=Integer.parseInt(mu.substring(10,12),16);


        Integer len=0;
        String length = "0000";
        String cmd_hex = "03";
        Integer cmd=Integer.parseInt(cmd_hex,16);


        Integer bb=f1+f2+vma+vmi+sec+min+hour+day+month+year+src0+src1+src2+src3+src4+src5+dest0+dest1+dest2+dest3+dest4+dest5+len+cmd;
        Integer check = bb &0xff;
        byte cc = (byte) check.intValue();
        String crc = ByteUtil.buqi3(toHex(cc));

        String message = headed+flowId+version+hex_sec+hex_min+hex_hour+hex_day+hex_month+hex_year+mu+src+length+cmd_hex+crc+"2323";
        log.debug("应答心跳包:"+message);
        return ByteUtil.toBytes(message);

    }

    /**
     * 同步时间
     *
     * @param iot 物联网
     * @return boolean
     * @throws ParseException 解析异常
     */
    public boolean syncTime(UserSmartIotProtocol iot) throws ParseException {

        String time="20" + iot.getYear() + "-" + iot.getMonth() + "-" + iot.getDay() + " " + iot.getHour() + ":"
                + iot.getMinute() + ":" + iot.getMinute();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Long date=sdf.parse(time).getTime();
        Calendar now = Calendar.getInstance();

        System.out.println(now.getTimeInMillis()-date);


        iot.setYear((byte) (now.get(Calendar.YEAR)-2000));
        iot.setMonth((byte) (now.get(Calendar.MONTH) + 1));
        iot.setDay((byte) now.get(Calendar.DAY_OF_MONTH));
        iot.setHour((byte) now.get(Calendar.HOUR_OF_DAY));
        iot.setMinute((byte) now.get(Calendar.MINUTE));
        iot.setSecond((byte) now.get(Calendar.SECOND));

        //用户传输装置时间是否和系统时间一致,不一致需要同步时间，发送同步时间指令
        if (now.getTimeInMillis()-date>60000){
            return true;
        }
        return false;
    }

    // 把byte 转化为两位十六进制数
    public static String toHex(byte b) {
        String result = Integer.toHexString(b & 0xFF);
        if (result.length() == 1) {
            result = '0' + result;
        }
        return result;
    }

    private String printHexByte(byte b) {
        return String.format("%02X", b);
    }

    private String printHexBytes(byte[] bytes) {
        String str = "";
        for (int i = 0; i < bytes.length; i++) {
            str += String.format("%02X", bytes[i]);
        }
        return str;
    }

    private String printHexShort(int s) {
        byte[] bytes = hexShort(s);
        return printHexBytes(bytes);
    }

    private byte[] hexShort(int s) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) ((s << 24) >> 24);
        bytes[1] = (byte) ((s << 16) >> 24);
        return bytes;
    }

}
